#include "stdafx.h"
#include "hzMath.h"



using namespace hz;
using namespace math;


// vector2d
vector2d::vector2d(void) 
: D3DXVECTOR2(0.0f, 0.0f) {
}

vector2d::vector2d(const vector2d& original) 
: D3DXVECTOR2(original) {
}

vector2d::vector2d(const float& X, const float& Y) 
: D3DXVECTOR2(X, Y) {
}

void vector2d::baryCentric(const vector2d& inputA, const vector2d& inputB, const vector2d& inputC, 
					  const float& factorF, const float& factorG) {
	D3DXVec2BaryCentric(this, &inputA, &inputB, &inputC, factorF, factorG);
}

void vector2d::catmullRom(const vector2d& inputA, const vector2d& inputB, const vector2d& inputC, const vector2d& inputD, 
						  float factor) {
	D3DXVec2CatmullRom(this, &inputA, &inputB, &inputC, &inputD, factor);
}

float vector2d::ccw(const vector2d& input) const {
	return D3DXVec2CCW(this, &input);
}

float vector2d::dot(const vector2d& input) const {
	return D3DXVec2Dot(this, &input);
}

void vector2d::hermite(const vector2d& posA, const vector2d& targetA, const vector2d& posB, const vector2d& targetB,
					   const float& factor) {
	D3DXVec2Hermite(this, &posA, &targetA, &posB, &targetB, factor);
}

float vector2d::length(void) const {
	return D3DXVec2Length(this);
}

float vector2d::lengthSq(void) const {
	return D3DXVec2LengthSq(this);
}

void vector2d::lerp(const vector2d& inputA, const vector2d& inputB, const float& factor) {
	D3DXVec2Lerp(this, &inputA, &inputB, factor);
}

void vector2d::maximize(const vector2d& inputA, const vector2d& inputB) {
	D3DXVec2Maximize(this, &inputA, &inputB);
}

void vector2d::minimize(const vector2d& inputA, const vector2d& inputB) {
	D3DXVec2Minimize(this, &inputA, &inputB);
}

void vector2d::normalize(void) {
	D3DXVec2Normalize(this, this);
}

void vector2d::scale(const float& factor) {
	D3DXVec2Scale(this, this, factor);
}



// vector3d
vector3d::vector3d(void) 
: D3DXVECTOR3(0.0f, 0.0f, 0.0f) {
}
vector3d::vector3d(const vector3d& original) 
: D3DXVECTOR3(original) {
}
vector3d::vector3d(const float& x, const float& y, const float& z) 
: D3DXVECTOR3(x, y, z) {
}

void vector3d::baryCentric(const vector3d& inputA, const vector3d& inputB, const vector3d& inputC,
						   const float& factorF, const float& factorG) {
	D3DXVec3BaryCentric(this, &inputA, &inputB, &inputC, factorF, factorG);
}

void vector3d::catmullRom(const vector3d& inputA, const vector3d& inputB, const vector3d& inputC, const vector3d& inputD,
						  const float& factor) {
	D3DXVec3CatmullRom(this, &inputA, &inputB, &inputC, &inputD, factor);
}

void vector3d::cross(const vector3d& inputA, const vector3d& inputB) {
	D3DXVec3Cross(this, &inputA, &inputB);
}

float vector3d::dot(const vector3d& input) const {
	return D3DXVec3Dot(this, &input);
}

void vector3d::hermite(const vector3d& posA, const vector3d& targetA, const vector3d& posB, const vector3d& targetB,
					   const float& factor) {
	D3DXVec3Hermite(this, &posA, &targetA, &posB, &targetB, factor);
}

float vector3d::length(void) const {
	return D3DXVec3Length(this);
}

float vector3d::lengthSq(void) const {
	return D3DXVec3LengthSq(this);
}

void vector3d::lerp(const vector3d& inputA, const vector3d& inputB, const float& factor) {
	D3DXVec3Lerp(this, &inputA, &inputB, factor);
}

void vector3d::maximize(const vector3d& inputA, const vector3d& inputB) {
	D3DXVec3Maximize(this, &inputA, &inputB);
}

void vector3d::minimize(const vector3d& inputA, const vector3d& inputB) {
	D3DXVec3Minimize(this, &inputA, &inputB);
}

void vector3d::normalize(void) {
	D3DXVec3Normalize(this, this);
}

void vector3d::scale(const float& factor) {
	D3DXVec3Scale(this, this, factor);
}

vector3d vector3d::operator-(const vector3d& right) const {
	return vector3d(this->x - right.x, this->y - right.y, this->z - right.z);
}

//vector3d& vector3d::operator=(const D3DXVECTOR3& right) {
//	*this = right;
//	return *this;
//}



// vector4d
vector4d::vector4d(void) 
: D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f) {
}
vector4d::vector4d(const vector4d& original) 
: D3DXVECTOR4(original) {
}

void vector4d::baryCentric(const vector4d& inputA, const vector4d& inputB, const vector4d& inputC,
						   const float& factorF, const float& factorG) {
	D3DXVec4BaryCentric(this, &inputA, &inputB, &inputC, factorF, factorG);
}

void vector4d::catmullRom(const vector4d& inputA, const vector4d& inputB, const vector4d& inputC, const vector4d& inputD,
						  const float& factor) {
	D3DXVec4CatmullRom(this, &inputA, &inputB, &inputC, &inputD, factor);
}

void vector4d::cross(const vector4d& inputA, const vector4d& inputB, const vector4d& inputC) {
	D3DXVec4Cross(this, &inputA, &inputB, &inputC);
}

float vector4d::dot(const vector4d& input) const {
	return D3DXVec4Dot(this, &input);
}

void vector4d::hermite(const vector4d& posA, const vector4d& targetA, const vector4d& posB, const vector4d& targetB,
					   const float& factor) {
	D3DXVec4Hermite(this, &posA, &targetA, &posB, &targetB, factor);
}

float vector4d::length(void) const {
	return D3DXVec4Length(this);
}

float vector4d::lengthSq(void) const {
	return D3DXVec4LengthSq(this);
}

void vector4d::lerp(const vector4d& inputA, const vector4d& inputB, const float& factor) {
	D3DXVec4Lerp(this, &inputA, &inputB, factor);
}

void vector4d::maximize(const vector4d& inputA, const vector4d& inputB) {
	D3DXVec4Maximize(this, &inputA, &inputB);
}

void vector4d::minimize(const vector4d& inputA, const vector4d& inputB) {
	D3DXVec4Minimize(this, &inputA, &inputB);
}

void vector4d::normalize(void) {
	D3DXVec4Normalize(this, this);
}

void vector4d::scale(const float& factor) {
	D3DXVec4Scale(this, this, factor);
}



// matrix
matrix::matrix(void) {
	identity();
}

matrix::matrix(const matrix& original) 
: D3DXMATRIX(original) {	
}

void matrix::affineTransformation(const float &scaling, 
								  const vector3d* rotationCenter, const quaternion* rotation, 
								  const vector3d* translation)  {
	D3DXMatrixAffineTransformation(this, scaling, rotationCenter, rotation, translation);
}

void matrix::affineTransformation(const float &scaling, 
								  const vector2d* rotationCenter, const float& rotation,
								  const vector2d* translation) {
	D3DXMatrixAffineTransformation2D(this, scaling, rotationCenter, rotation, translation);
}

void matrix::decompose(vector3d& outScale, quaternion& outRotation, vector3d& outTranslation) {
	D3DXMatrixDecompose(&outScale, &outRotation, &outTranslation, this);
}

float matrix::determinat(void) const{
	return D3DXMatrixDeterminant(this);
}

void matrix::identity(void) {
	D3DXMatrixIdentity(this);
}

void matrix::inverse(float* Determinant) {
	D3DXMatrixInverse(this, Determinant, this);
}

bool matrix::isIdentity(void) const {
	return (bool)D3DXMatrixIsIdentity(this);
}

void matrix::lookAtLH(const vector3d& pos, const vector3d& at, const vector3d& up) {
	D3DXMatrixLookAtLH(this, &pos, &at, &up);
}

void matrix::lookAtRH(const vector3d& pos, const vector3d& at, const vector3d& up) {
	D3DXMatrixLookAtRH(this, &pos, &at, &up);
}

void matrix::projectionOrthoLH(const float& viewWidth, const float& viewHeight, const float& nearZ, const float& farZ) {
	D3DXMatrixOrthoLH(this, viewWidth, viewHeight, nearZ, farZ);
}

void matrix::projectionOrthoRH(const float& viewWidth, const float& viewHeight, const float& nearZ, const float& farZ) {
	D3DXMatrixOrthoRH(this, viewWidth, viewHeight, nearZ, farZ);
}

void matrix::projectionOrthoOffCenterLH(const float& left, const float& right,
								const float& bottom, const float& top,
								const float& nearZ, const float& farZ) {
	D3DXMatrixOrthoOffCenterLH(this, left, right, bottom, top, nearZ, farZ);
}

void matrix::projectionOrthoOffCenterRH(const float& left, const float& right,
								const float& bottom, const float& top,
								const float& nearZ, const float& farZ) {
	D3DXMatrixOrthoOffCenterRH(this, left, right, bottom, top, nearZ, farZ);
}

void matrix::projectionPerspectiveForLH(const float& fovy, const float&aspect, const float& nearPlane, const float& FarPlane) {
	D3DXMatrixPerspectiveFovLH(this, fovy, aspect, nearPlane, FarPlane);
}

void matrix::projectionPerspectiveForRH(const float& fovy, const float&aspect, const float& nearPlane, const float& FarPlane) {
	D3DXMatrixPerspectiveFovRH(this, fovy, aspect, nearPlane, FarPlane);
}

void matrix::projectionPerspectiveLH(const float& viewPlaneWidth, const float& viewPlaneHeight, 
							 const float& nearPlane, const float& FarPlane) {
	D3DXMatrixPerspectiveLH(this, viewPlaneWidth, viewPlaneHeight, nearPlane, FarPlane);
}

void matrix::projectionPerspectiveRH(const float& viewPlaneWidth, const float& viewPlaneHeight, 
							 const float& nearPlane, const float& FarPlane) {
	D3DXMatrixPerspectiveLH(this, viewPlaneWidth, viewPlaneHeight, nearPlane, FarPlane);
}

void matrix::projectionPerspectiveOffCenterLH(const float& left, const float& right,
							    	  const float& bottom, const float& top,
									  const float& nearZ, const float& farZ) {
	D3DXMatrixPerspectiveOffCenterLH(this, left, right, bottom, top, nearZ, farZ);
}

void matrix::projectionPerspectiveOffCenterRH(const float& left, const float& right,
							    	  const float& bottom, const float& top,
									  const float& nearZ, const float& farZ) {
	D3DXMatrixPerspectiveOffCenterLH(this, left, right, bottom, top, nearZ, farZ);
}

void matrix::reflect(const plane& input) {
	D3DXMatrixReflect(this, &input);
}

void matrix::rotation(const vector3d& axis, const float& angle) {
	D3DXMatrixRotationAxis(this, &axis, angle);
}

void matrix::rotation(const quaternion& input) {
	D3DXMatrixRotationQuaternion(this, &input);
}

void matrix::rotation(const float& yaw, const float& pitch, const float& roll) {
	D3DXMatrixRotationYawPitchRoll(this, yaw, pitch, roll);
}

void matrix::rotationX(const float& angle) {
	D3DXMatrixRotationX(this, angle);
}

void matrix::rotationY(const float& angle) {
	D3DXMatrixRotationY(this, angle);
}

void matrix::rotationZ(const float& angle) {
	D3DXMatrixRotationZ(this, angle);
}

void matrix::scaling(const float& x, const float& y, const float& z) {
	D3DXMatrixScaling(this, x, y, z);
}

void matrix::shadow(const vector4d& light, const plane& inputPlane) {
	D3DXMatrixShadow(this, &light, &inputPlane);
}

void matrix::transformation(const vector3d* scalingCenter, const quaternion* scalingRotation, const vector3d* scaling,
							const vector3d* rotationCenter, const quaternion* rotation,
							const vector3d* translation) {
	D3DXMatrixTransformation(this, scalingCenter, scalingRotation, scaling, rotationCenter, rotation, translation);
}

void matrix::transformation(const vector2d* scalingCenter, const float& scalingRotation, const vector2d* scaling, 
							const vector2d* rotationCenter, const float& rotation, 
							const vector2d* translation) {
	D3DXMatrixTransformation2D(this, scalingCenter, scalingRotation, scaling, rotationCenter, rotation, translation);
}

void matrix::translation(const float& x, const float& y, const float& z) {
	D3DXMatrixTranslation(this, x, y, z);
}

void matrix::translation(const vector3d& movement) {
	this->translation(movement.x, movement.y, movement.z);
}

void matrix::transform(plane& output, const plane& input) const {
	D3DXPlaneTransform(&output, &input, this);
}

void matrix::transform(vector4d& output, const vector2d& input) const {
	D3DXVec2Transform(&output, &input, this);
}

void matrix::transform(vector4d& output, const vector3d& input) const {
	D3DXVec3Transform(&output, &input, this);
}

void matrix::transform(vector4d& output, const vector4d& input) const {
	D3DXVec4Transform(&output, &input, this);
}

void matrix::transformCoord(vector2d& output, const vector2d& input) const {
	D3DXVec2TransformCoord(&output, &input, this);
}

void matrix::transformCoord(vector3d& output, const vector3d& input) const {
	D3DXVec3TransformCoord(&output, &input, this);
}

void matrix::transformNormal(vector2d& output, const vector2d& input) const {
	D3DXVec2TransformNormal(&output, &input, this);
}

void matrix::transformNormal(vector3d& output, const vector3d& input) const {
	D3DXVec3TransformNormal(&output, &input, this);
}

matrix matrix::getInverse(float* Determinant) {
	matrix temp(*this);	
	temp.inverse(Determinant);	
	return temp;	
}

matrix& matrix::operator*(const matrix& right) {
	D3DXMatrixMultiply(this, this, &right);
	return *this;
}




// quaternion
void quaternion::baryCentric(const quaternion& inputA, const quaternion& inputB, const quaternion& inputC,
							 const float& factorF, const float& factorG) {
	D3DXQuaternionBaryCentric(this, &inputA, &inputB, &inputC, factorF, factorG);
}

void quaternion::conjugate(void) {
	D3DXQuaternionConjugate(this, this);
}

float quaternion::dot(const quaternion& input) const {
	return D3DXQuaternionDot(this, &input);
}

void quaternion::exp(void) {
	D3DXQuaternionExp(this, this);
}

void quaternion::identity(void) {
	D3DXQuaternionIdentity(this);
}

void quaternion::inverse(void) {
	D3DXQuaternionInverse(this, this);
}

bool quaternion::isIdentity(void) const {
	return D3DXQuaternionIsIdentity(this);
}

float quaternion::length(void) const {
	return D3DXQuaternionLength(this);
}

float quaternion::lengthSq(void) const {
	return D3DXQuaternionLengthSq(this);
}

void quaternion::naturalLogarithm(void) {
	D3DXQuaternionLn(this, this);
}

void quaternion::normalize(void) {
	D3DXQuaternionNormalize(this, this);
}

void quaternion::rotation(const vector3d& axis, const float& angle) {
	D3DXQuaternionRotationAxis(this, &axis, angle);
}

void quaternion::rotation(const matrix& rotation) {
	D3DXQuaternionRotationMatrix(this, &rotation);
}

void quaternion::rotation(const float& yaw, const float& pitch, const float& roll) {
	D3DXQuaternionRotationYawPitchRoll(this, yaw, pitch, roll);
}

void quaternion::slerp(const quaternion& inputA, const quaternion& inputB, const float& far) {
	//D3DXQuaternionSlerp(this, &inputA, &inputB, far);
	assert(0);
}

void quaternion::Squad(const quaternion& inputA, const quaternion& inputB, 
					   const quaternion& inputC, const quaternion& inputD, const float& t) {
	D3DXQuaternionSquad(this, &inputA, &inputB, &inputC, &inputD, t);
}


// plane
plane::plane(void) 
: D3DXPLANE(0.0f, 1.0f, 0.0f, 0.0f) {
}

plane::plane(const plane& original) 
: D3DXPLANE(original) {
}

float plane::dot(const vector4d& input) {
	return D3DXPlaneDot(this, &input);
}

float plane::dotCoord(const vector3d& input) {
	return D3DXPlaneDotCoord(this, &input);
}

float plane::dotNormal(const vector3d& input) {
	return D3DXPlaneDotNormal(this, &input);
}

void plane::build(const vector3d& point, const vector3d& normal) {
	D3DXPlaneFromPointNormal(this, &point, &normal);
}

void plane::build(const triangle3d& input) {
	D3DXPlaneFromPoints(this, &input.vertexA, &input.vertexB, &input.vertexC);
}

void plane::intersectLine(vector3d& outPoint, const line3d& input) {
	D3DXPlaneIntersectLine(&outPoint, this, &input.start, &input.end);
}

void plane::normalize(void) {
	D3DXPlaneNormalize(this, this);
}

void plane::scale(const float& factor) {
	D3DXPlaneScale(this, this, factor);
}

void plane::transform(const matrix& input) {
	input.transform(*this, *this);
}


// color
color::color(void) 
: D3DXCOLOR((DWORD)0){
}
color::color(const color& original) 
: D3DXCOLOR(original) {
}
color::color(const color_compound& original)
: D3DXCOLOR(original) {	
}

void color::add(const color& input) {
	D3DXColorAdd(this, this,& input);
}

void color::add(const color& inputA, const color& inputB) { 
	D3DXColorAdd(this,& inputA,& inputB);
}

void color::adjustContrast(float contrast) { 
	D3DXColorAdjustContrast(this, this, contrast); 
}

void color::adjustSaturation(float saturation) {
	D3DXColorAdjustSaturation(this, this, saturation);
}

void color::interpolation(const color& input, const float& inputWeight) {
	D3DXColorLerp(this, this,& input, inputWeight);
}

void color::modulate(const color& input) {
	D3DXColorModulate(this, this,& input);
}

void color::negative(void) {
	D3DXColorNegative(this, this);
}

void color::scale(float scale) {
	D3DXColorScale(this, this, scale);
}

void color::subtract(const color& input) {
	D3DXColorSubtract(this, this,& input);
}
				
void color::subtract(const color& inputA, const color&inputB) {
	D3DXColorSubtract(this,& inputA,& inputB);
}



// color_compound
color_compound::color_compound(void) {
	set(0,0,0,0);
}

color_compound::color_compound(const int& A, const int& R, const int& G, const int& B) {
	set(A,R,G,B);
}

color_compound::color_compound(const color& color) {
	set(color);
}

void color_compound::set(const color& color) {
	set( (int)((float)255 * color.a),
	  	 (int)((float)255 * color.r),
		 (int)((float)255 * color.g),
		 (int)((float)255 * color.b));
}

void color_compound::set(const int& R, const int& G, const int& B) {
	value = D3DCOLOR_XRGB(R, G, B);
}
void color_compound::set(const int& A, const int& R, const int& G, const int& B) {
	value = D3DCOLOR_ARGB(A, R, G, B);
}

unsigned int color_compound::a(void) const {
	return (value >> 24) & 0xff;
}

unsigned int color_compound::r(void) const {
	return (value >> 16) & 0xff;
}

unsigned int color_compound::g(void) const {
	return (value >> 8) & 0xff;
}

unsigned int color_compound::b(void) const {
	return value & 0xff;
}

color_compound::operator unsigned int() {
	return value;
}
color_compound::operator unsigned int() const {
	return value;
}